# Linux kernel-native Makefile ("Kbuild") for libwolfssl.ko
#
# Copyright (C) 2006-2020 wolfSSL Inc.
#
# This file is part of wolfSSL.
#
# wolfSSL is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# wolfSSL is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA

SHELL=/bin/bash

ifeq "$(WOLFSSL_OBJ_FILES)" ""
    $(error $$WOLFSSL_OBJ_FILES is unset.)
endif

ifeq "$(WOLFSSL_CFLAGS)" ""
    $(error $$WOLFSSL_CFLAGS is unset.)
endif

WOLFSSL_CFLAGS += -Wframe-larger-than=$(MAX_STACK_FRAME_SIZE) -mpreferred-stack-boundary=4

obj-m := libwolfssl.o

WOLFSSL_OBJ_TARGETS=$(patsubst %, $(obj)/%, $(WOLFSSL_OBJ_FILES))

$(obj)/linuxkm/module_exports.o: $(WOLFSSL_OBJ_TARGETS)

# this mechanism only works in kernel 5.x+ (fallback to hardcoded value)
hostprogs := linuxkm/get_thread_size
always-y := $(hostprogs)
HOST_EXTRACFLAGS += $(NOSTDINC_FLAGS) $(LINUXINCLUDE) $(KBUILD_CFLAGS) -static

# this rule is needed to get build to succeed in 4.x (get_thread_size still doesn't get built)
$(obj)/linuxkm/get_thread_size: $(src)/linuxkm/get_thread_size.c

$(WOLFSSL_OBJ_TARGETS): | $(obj)/linuxkm/get_thread_size
KERNEL_THREAD_STACK_SIZE=$(shell test -x $(obj)/linuxkm/get_thread_size && $(obj)/linuxkm/get_thread_size || echo 16384)
MAX_STACK_FRAME_SIZE=$(shell echo $$(( $(KERNEL_THREAD_STACK_SIZE) / 4)))

libwolfssl-y := $(WOLFSSL_OBJ_FILES) linuxkm/module_hooks.o linuxkm/module_exports.o

WOLFSSL_CFLAGS_NO_VECTOR_INSNS := $(CFLAGS_SIMD_DISABLE) $(CFLAGS_FPU_DISABLE)
ifeq "$(ENABLED_ASM)" "yes"
    WOLFSSL_CFLAGS_YES_VECTOR_INSNS := $(CFLAGS_SIMD_ENABLE) $(CFLAGS_FPU_DISABLE) $(CFLAGS_AUTO_VECTORIZE_DISABLE)
else
    WOLFSSL_CFLAGS_YES_VECTOR_INSNS := $(WOLFSSL_CFLAGS_NO_VECTOR_INSNS)
endif

ccflags-y = $(WOLFSSL_CFLAGS) $(WOLFSSL_CFLAGS_NO_VECTOR_INSNS)

$(obj)/libwolfssl.mod.o: ccflags-y :=
$(obj)/wolfcrypt/test/test.o: ccflags-y += -DNO_MAIN_DRIVER

$(obj)/wolfcrypt/src/aes.o: ccflags-y = $(WOLFSSL_CFLAGS) $(WOLFSSL_CFLAGS_YES_VECTOR_INSNS)

asflags-y := $(WOLFSSL_ASFLAGS) $(ASFLAGS_FPUSIMD_DISABLE)

# after the C wrapper for a vectorized algorithm has been equipped with {SAVE,RESTORE}_VECTOR_REGISTERS(),
# it can be safely included here:
$(obj)/wolfcrypt/src/aes_asm.o: asflags-y = $(WOLFSSL_ASFLAGS) $(ASFLAGS_FPU_DISABLE_SIMD_ENABLE)
$(obj)/wolfcrypt/src/aes_gcm_asm.o: asflags-y = $(WOLFSSL_ASFLAGS) $(ASFLAGS_FPU_DISABLE_SIMD_ENABLE)

# these _asms are kernel-compatible, but they still irritate objtool:
$(obj)/wolfcrypt/src/aes_asm.o: OBJECT_FILES_NON_STANDARD := y
$(obj)/wolfcrypt/src/aes_gcm_asm.o: OBJECT_FILES_NON_STANDARD := y

# auto-generate the exported symbol list, leveraging the WOLFSSL_API visibility tags.
# exclude symbols that don't match wc_* or wolf*.
$(src)/linuxkm/module_exports.c: $(src)/linuxkm/module_exports.c.template $(WOLFSSL_OBJ_TARGETS)
	@cp $< $@
	@readelf --symbols --wide $(WOLFSSL_OBJ_TARGETS) |				\
		awk '/^ *[0-9]+: / {							\
		  if ($$8 !~ /^(wc_|wolf)/){next;}					\
		  if (($$4 == "FUNC") && ($$5 == "GLOBAL") && ($$6 == "DEFAULT")) {	\
		    print "EXPORT_SYMBOL_NS(" $$8 ", WOLFSSL);";    		  	\
		  }									\
		}' >> $@
	@echo -e '#ifndef NO_CRYPT_TEST\nEXPORT_SYMBOL_NS(wolfcrypt_test, WOLFSSL);\n#endif' >> $@

clean-files := module_exports.c
